import os
import re
import sys
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D

class TextTo3DGenerator:
    """通过文本描述生成3D模型的类"""
    def __init__(self, output_dir="output/text3d"):
        self.output_dir = output_dir
        self._ensure_dir(output_dir)
        self.shapes = {
            "cube": self._create_cube,
            "cuboid": self._create_cuboid,
            "cylinder": self._create_cylinder,
            "pyramid": self._create_pyramid,
            "sphere": self._create_sphere,
            "building": self._create_building,
            "tower": self._create_tower
        }
        self.colors = {
            "red": "#FF0000", "红色": "#FF0000", 
            "green": "#00FF00", "绿色": "#00FF00", 
            "blue": "#0000FF", "蓝色": "#0000FF",
            "yellow": "#FFFF00", "黄色": "#FFFF00", 
            "cyan": "#00FFFF", "青色": "#00FFFF", 
            "magenta": "#FF00FF", "品红": "#FF00FF",
            "white": "#FFFFFF", "白色": "#FFFFFF", 
            "black": "#000000", "黑色": "#000000", 
            "gray": "#808080", "灰色": "#808080",
            "brown": "#A52A2A", "棕色": "#A52A2A", 
            "orange": "#FFA500", "橙色": "#FFA500", 
            "purple": "#800080", "紫色": "#800080"
        }
        
    def _ensure_dir(self, directory):
        """确保目录存在"""
        if not os.path.exists(directory):
            os.makedirs(directory)
            
    def parse_text(self, text):
        """解析文本描述，提取3D模型参数"""
        # 默认参数
        params = {
            "type": "cube",
            "width": 1.0,
            "height": 1.0,
            "depth": 1.0,
            "radius": 0.5,
            "color": "#4C9AFE",
            "position": [0, 0, 0],
            "segments": 32
        }
        
        # 提取形状类型
        # 中文形状名称映射
        shape_mapping = {
            "立方体": "cube",
            "长方体": "cuboid",
            "圆柱体": "cylinder",
            "金字塔": "pyramid",
            "球体": "sphere",
            "建筑": "building",
            "塔楼": "tower"
        }
        
        # 先检查中文形状名称
        for cn_shape, en_shape in shape_mapping.items():
            if cn_shape in text:
                params["type"] = en_shape
                break
        
        # 如果没找到中文名称，再检查英文形状名称
        if params["type"] == "cube":  # 如果仍然是默认值
            for shape in self.shapes.keys():
                if shape in text.lower():
                    params["type"] = shape
                    break
                
        # 提取颜色
        # 直接使用正则表达式匹配所有可能的颜色模式
        color_match = re.search(r'(红|蓝|绿|黄|青|品红|白|黑|灰|棕|橙|紫)色', text)
        if color_match:
            color_name = color_match.group(1) + "色"
            if color_name in self.colors:
                params["color"] = self.colors[color_name]
        else:
            # 尝试匹配英文颜色名称
            for color_name in ["red", "blue", "green", "yellow", "cyan", "magenta", 
                              "white", "black", "gray", "brown", "orange", "purple"]:
                if re.search(r'\b' + color_name + r'\b', text.lower()):
                    params["color"] = self.colors[color_name]
                    break
                
        # 提取尺寸
        width_match = re.search(r'宽度[：:]*\s*(\d+\.?\d*)|width[：:]*\s*(\d+\.?\d*)', text, re.IGNORECASE)
        if width_match:
            # 获取匹配的组（中文或英文）
            value = width_match.group(1) if width_match.group(1) else width_match.group(2)
            params["width"] = float(value)
            
        height_match = re.search(r'高度[：:]*\s*(\d+\.?\d*)|height[：:]*\s*(\d+\.?\d*)', text, re.IGNORECASE)
        if height_match:
            value = height_match.group(1) if height_match.group(1) else height_match.group(2)
            params["height"] = float(value)
            
        depth_match = re.search(r'深度[：:]*\s*(\d+\.?\d*)|depth[：:]*\s*(\d+\.?\d*)', text, re.IGNORECASE)
        if depth_match:
            value = depth_match.group(1) if depth_match.group(1) else depth_match.group(2)
            params["depth"] = float(value)
            
        radius_match = re.search(r'半径[：:]*\s*(\d+\.?\d*)|radius[：:]*\s*(\d+\.?\d*)', text, re.IGNORECASE)
        if radius_match:
            value = radius_match.group(1) if radius_match.group(1) else radius_match.group(2)
            params["radius"] = float(value)
                
        return params
    
    def generate_model(self, text_description, output_filename=None):
        """根据文本描述生成3D模型"""
        params = self.parse_text(text_description)
        
        if params["type"] not in self.shapes:
            raise ValueError(f"不支持的形状类型: {params['type']}")
            
        if not output_filename:
            output_filename = f"{params['type']}_{int(params['width'])}x{int(params['height'])}"
            
        # 调用相应的形状创建函数
        shape_func = self.shapes[params["type"]]
        fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={"projection": "3d"})
        shape_func(ax, params)
        
        # 设置图形属性
        ax.set_box_aspect([1, 1, 1])
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')
        
        # 保存图形
        output_path = os.path.join(self.output_dir, f"{output_filename}.png")
        plt.tight_layout()
        plt.savefig(output_path, dpi=150)
        plt.close(fig)
        
        # 保存参数
        params_path = os.path.join(self.output_dir, f"{output_filename}_params.txt")
        with open(params_path, "w", encoding="utf-8") as f:
            f.write(f"模型类型: {params['type']}\n")
            f.write(f"尺寸: 宽={params['width']}, 高={params['height']}, 深={params['depth']}\n")
            if params['type'] in ['cylinder', 'sphere']:
                f.write(f"半径: {params['radius']}\n")
            f.write(f"颜色: {params['color']}\n")
            f.write(f"位置: {params['position']}\n")
            
        return output_path
        
    def generate_multi_cubes(self, cubes_params, output_filename="multi_cubes", show_z_plane=False):
        """
        在同一空间生成多个立方体
        
        参数:
        cubes_params: 列表，每个元素是一个字典，包含立方体的参数
                     必须包含 'size'(大小) 和 'position'(中心点坐标) 键
                     可选包含 'color'(颜色) 键
                     可选包含 'rotation_x', 'rotation_y', 'rotation_z' 键控制旋转角度
        output_filename: 输出文件名
        show_z_plane: 是否显示灰色的z=0平面
        
        示例:
        cubes_params = [
            {'size': [2, 2, 2], 'position': [0, 0, 0], 'color': '#FF0000', 'rotation_y': 45},
            {'size': [1, 1, 1], 'position': [3, 3, 0], 'color': '#0000FF', 'rotation_x': 30}
        ]
        """
        # 创建3D图形
        fig, ax = plt.subplots(figsize=(10, 8), subplot_kw={"projection": "3d"})
        
        # 跟踪所有立方体的边界，用于设置坐标轴范围
        all_vertices = []
        
        # 为每个立方体生成3D模型
        for i, cube_params in enumerate(cubes_params):
            # 提取参数
            if 'size' not in cube_params or 'position' not in cube_params:
                raise ValueError(f"立方体 #{i+1} 缺少必要参数 'size' 或 'position'")
                
            size = cube_params['size']
            if len(size) != 3:
                raise ValueError(f"立方体 #{i+1} 的 'size' 必须是包含3个元素的列表 [宽, 高, 深]")
                
            position = cube_params['position']
            if len(position) != 3:
                raise ValueError(f"立方体 #{i+1} 的 'position' 必须是包含3个元素的列表 [x, y, z]")
                
            # 设置默认颜色，如果没有提供
            color = cube_params.get('color', '#4C9AFE')
            
            # 获取旋转角度（如果有）
            rotation_x = cube_params.get("rotation_x", 0)  # 绕X轴旋转的角度
            rotation_y = cube_params.get("rotation_y", 0)  # 绕Y轴旋转的角度
            rotation_z = cube_params.get("rotation_z", 0)  # 绕Z轴旋转的角度
            
            # 提取尺寸和位置（将position的z视为底面高度）
            w, h, d = size
            x, y, z_base = position
            
            # 根据底面高度计算中心z，使未旋转时底面在z_base
            z = z_base + h/2
            
            # 计算立方体的顶点坐标（相对于中心点）
            x_offset = w / 2
            y_offset = d / 2
            z_offset = h / 2
            
            vertices = [
                [x - x_offset, y - y_offset, z - z_offset], 
                [x + x_offset, y - y_offset, z - z_offset],
                [x + x_offset, y + y_offset, z - z_offset], 
                [x - x_offset, y + y_offset, z - z_offset],
                [x - x_offset, y - y_offset, z + z_offset], 
                [x + x_offset, y - y_offset, z + z_offset],
                [x + x_offset, y + y_offset, z + z_offset], 
                [x - x_offset, y + y_offset, z + z_offset]
            ]
            
            # 应用旋转变换（绕立方体中心）
            if rotation_x != 0 or rotation_y != 0 or rotation_z != 0:
                rx = np.radians(rotation_x)
                ry = np.radians(rotation_y)
                rz = np.radians(rotation_z)
                
                Rx = np.array([[1, 0, 0],[0, np.cos(rx), -np.sin(rx)],[0, np.sin(rx), np.cos(rx)]])
                Ry = np.array([[np.cos(ry), 0, np.sin(ry)],[0, 1, 0],[-np.sin(ry), 0, np.cos(ry)]])
                Rz = np.array([[np.cos(rz), -np.sin(rz), 0],[np.sin(rz), np.cos(rz), 0],[0, 0, 1]])
                R = Rz @ Ry @ Rx
                center = np.array([x, y, z])
                for i in range(len(vertices)):
                    v = np.array(vertices[i]) - center
                    vertices[i] = (R @ v) + center
            
            # 将立方体沿z轴平移，使其最低点恰好位于z_base（通常为0）
            verts_arr = np.array(vertices)
            min_z = np.min(verts_arr[:, 2])
            dz = z_base - min_z
            if dz != 0:
                verts_arr[:, 2] += dz
                vertices = verts_arr.tolist()
                z += dz  # 更新中心z，便于后续边界计算
            
            all_vertices.extend(vertices)
            
            # 定义6个面
            faces = [
                [vertices[0], vertices[1], vertices[2], vertices[3]],  # 底面
                [vertices[4], vertices[5], vertices[6], vertices[7]],  # 顶面
                [vertices[0], vertices[1], vertices[5], vertices[4]],  # 前面
                [vertices[1], vertices[2], vertices[6], vertices[5]],  # 右面
                [vertices[2], vertices[3], vertices[7], vertices[6]],  # 后面
                [vertices[3], vertices[0], vertices[4], vertices[7]]   # 左面
            ]
            
            # 创建3D多边形集合
            poly3d = Poly3DCollection(faces, alpha=0.95, linewidths=1, edgecolors='black')
            poly3d.set_facecolor(color)
            ax.add_collection3d(poly3d)
        
        # 计算所有立方体的边界，设置坐标轴范围
        if all_vertices:
            all_vertices = np.array(all_vertices)
            x_min, y_min, z_min = np.min(all_vertices, axis=0)
            x_max, y_max, z_max = np.max(all_vertices, axis=0)
            
            # 计算中心点和最大范围（下限固定为z=0，不展示z<0空间）
            mid_x = (x_min + x_max) / 2
            mid_y = (y_min + y_max) / 2
            z_min = 0
            mid_z = (z_max) / 2
            
            max_range = max(x_max - x_min, y_max - y_min, z_max - z_min) * 0.6
            
            ax.set_xlim(mid_x - max_range, mid_x + max_range)
            ax.set_ylim(mid_y - max_range, mid_y + max_range)
            ax.set_zlim(0, z_max + max_range * 0.5)
            
            # 添加灰色的z=0平面（如果需要）
            if show_z_plane:
                xlim = ax.get_xlim()
                ylim = ax.get_ylim()
                x_range = np.array([xlim[0], xlim[1]])
                y_range = np.array([ylim[0], ylim[1]])
                xx, yy = np.meshgrid(x_range, y_range)
                zz = np.zeros_like(xx)
                ax.plot_surface(xx, yy, zz, color='gray', alpha=0.3)
        
        # 设置图形属性
        ax.set_box_aspect([1, 1, 1])
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')
        
        # 保存图形
        output_path = os.path.join(self.output_dir, f"{output_filename}.png")
        plt.tight_layout()
        plt.savefig(output_path, dpi=150)
        
        # 导出OBJ文件
        obj_path = os.path.join(self.output_dir, f"{output_filename}.obj")
        self._export_multi_cubes_obj(obj_path, cubes_params)
        
        # 保存参数
        params_path = os.path.join(self.output_dir, f"{output_filename}_params.txt")
        with open(params_path, "w", encoding="utf-8") as f:
            f.write(f"模型类型: 多立方体\n")
            f.write(f"立方体数量: {len(cubes_params)}\n\n")
            
            for i, cube_params in enumerate(cubes_params):
                f.write(f"立方体 #{i+1}:\n")
                f.write(f"  尺寸: {cube_params['size']}\n")
                f.write(f"  位置: {cube_params['position']}\n")
                f.write(f"  颜色: {cube_params.get('color', '#4C9AFE')}\n")
                f.write(f"  rotation_z: {cube_params.get('rotation_z', 0)}\n\n")
        
        plt.close(fig)
        print(f"已生成多立方体3D模型: {output_path}")
        print(f"已导出OBJ文件: {obj_path}")
        
        return output_path
        
    def _export_multi_cubes_obj(self, obj_path, cubes_params):
        """导出多个立方体的OBJ文件"""
        with open(obj_path, "w") as f:
            f.write("# 多立方体OBJ文件\n")
            
            vertex_count = 1  # OBJ文件中顶点索引从1开始
            
            for i, cube_params in enumerate(cubes_params):
                size = cube_params['size']
                position = cube_params['position']
                color = cube_params.get('color', '#4C9AFE')
                rotation_x = cube_params.get('rotation_x', 0)
                rotation_y = cube_params.get('rotation_y', 0)
                rotation_z = cube_params.get('rotation_z', 0)
                
                # 提取尺寸和位置（将position的z视为底面高度）
                w, h, d = size
                x, y, z_base = position
                
                # 根据底面高度计算中心z
                z = z_base + h/2
                
                # 计算立方体的顶点坐标（相对于中心点）
                x_offset = w / 2
                y_offset = d / 2
                z_offset = h / 2
                
                # 写入立方体注释
                f.write(f"\n# 立方体 #{i+1}\n")
                
                vertices = [
                    [x - x_offset, y - y_offset, z - z_offset], 
                    [x + x_offset, y - y_offset, z - z_offset],
                    [x + x_offset, y + y_offset, z - z_offset], 
                    [x - x_offset, y + y_offset, z - z_offset],
                    [x - x_offset, y - y_offset, z + z_offset], 
                    [x + x_offset, y - y_offset, z + z_offset],
                    [x + x_offset, y + y_offset, z + z_offset], 
                    [x - x_offset, y + y_offset, z + z_offset]
                ]
                
                # 应用旋转（如有）
                if rotation_x != 0 or rotation_y != 0 or rotation_z != 0:
                    rx = np.radians(rotation_x)
                    ry = np.radians(rotation_y)
                    rz = np.radians(rotation_z)
                    Rx = np.array([[1,0,0],[0,np.cos(rx),-np.sin(rx)],[0,np.sin(rx),np.cos(rx)]])
                    Ry = np.array([[np.cos(ry),0,np.sin(ry)],[0,1,0],[-np.sin(ry),0,np.cos(ry)]])
                    Rz = np.array([[np.cos(rz),-np.sin(rz),0],[np.sin(rz),np.cos(rz),0],[0,0,1]])
                    R = Rz @ Ry @ Rx
                    center = np.array([x, y, z])
                    for vi in range(len(vertices)):
                        v = np.array(vertices[vi]) - center
                        vertices[vi] = (R @ v) + center
                
                # 沿z轴平移，使最低点位于z_base
                verts_arr = np.array(vertices)
                min_z = np.min(verts_arr[:,2])
                dz = z_base - min_z
                if dz != 0:
                    verts_arr[:,2] += dz
                    vertices = verts_arr.tolist()
                
                # 写入顶点
                for v in vertices:
                    f.write(f"v {v[0]} {v[1]} {v[2]}\n")
                
                # 写入面（注意OBJ文件中顶点索引从1开始）
                f.write(f"f {vertex_count} {vertex_count+1} {vertex_count+2} {vertex_count+3}\n")  # 底面
                f.write(f"f {vertex_count+4} {vertex_count+5} {vertex_count+6} {vertex_count+7}\n")  # 顶面
                f.write(f"f {vertex_count} {vertex_count+1} {vertex_count+5} {vertex_count+4}\n")  # 前面
                f.write(f"f {vertex_count+1} {vertex_count+2} {vertex_count+6} {vertex_count+5}\n")  # 右面
                f.write(f"f {vertex_count+2} {vertex_count+3} {vertex_count+7} {vertex_count+6}\n")  # 后面
                f.write(f"f {vertex_count+3} {vertex_count} {vertex_count+4} {vertex_count+7}\n")  # 左面
                
                vertex_count += 8  # 每个立方体有8个顶点
    
    def _create_cube(self, ax, params):
        """创建立方体"""
        return self._create_cuboid(ax, params)
    
    def _create_cuboid(self, ax, params):
        """创建长方体"""
        w, h, d = params["width"], params["height"], params["depth"]
        x, y, z = params["position"]
        color = params["color"]
        
        # 获取旋转角度（如果有）
        rotation_x = params.get("rotation_x", 0)  # 绕X轴旋转的角度
        rotation_y = params.get("rotation_y", 0)  # 绕Y轴旋转的角度
        rotation_z = params.get("rotation_z", 0)  # 绕Z轴旋转的角度
        
        # 定义8个顶点
        vertices = [
            [x, y, z], [x+w, y, z], [x+w, y+d, z], [x, y+d, z],
            [x, y, z+h], [x+w, y, z+h], [x+w, y+d, z+h], [x, y+d, z+h]
        ]
        
        # 应用旋转变换
        if rotation_x != 0 or rotation_y != 0 or rotation_z != 0:
            # 将角度转换为弧度
            rx = np.radians(rotation_x)
            ry = np.radians(rotation_y)
            rz = np.radians(rotation_z)
            
            # 创建旋转矩阵
            # 绕X轴旋转矩阵
            Rx = np.array([
                [1, 0, 0],
                [0, np.cos(rx), -np.sin(rx)],
                [0, np.sin(rx), np.cos(rx)]
            ])
            
            # 绕Y轴旋转矩阵
            Ry = np.array([
                [np.cos(ry), 0, np.sin(ry)],
                [0, 1, 0],
                [-np.sin(ry), 0, np.cos(ry)]
            ])
            
            # 绕Z轴旋转矩阵
            Rz = np.array([
                [np.cos(rz), -np.sin(rz), 0],
                [np.sin(rz), np.cos(rz), 0],
                [0, 0, 1]
            ])
            
            # 组合旋转矩阵
            R = np.dot(Rz, np.dot(Ry, Rx))
            
            # 计算旋转中心（立方体的中心）
            center = np.array([x + w/2, y + d/2, z + h/2])
            
            # 对每个顶点应用旋转
            for i in range(len(vertices)):
                # 将顶点转换为相对于中心的坐标
                v = np.array(vertices[i]) - center
                # 应用旋转
                v_rotated = np.dot(R, v)
                # 转换回原始坐标系
                vertices[i] = v_rotated + center
        
        # 定义6个面
        faces = [
            [vertices[0], vertices[1], vertices[2], vertices[3]],  # 底面
            [vertices[4], vertices[5], vertices[6], vertices[7]],  # 顶面
            [vertices[0], vertices[1], vertices[5], vertices[4]],  # 前面
            [vertices[1], vertices[2], vertices[6], vertices[5]],  # 右面
            [vertices[2], vertices[3], vertices[7], vertices[6]],  # 后面
            [vertices[3], vertices[0], vertices[4], vertices[7]]   # 左面
        ]
        
        # 创建3D多边形集合
        poly3d = Poly3DCollection(faces, alpha=0.95, linewidths=1, edgecolors='black')
        poly3d.set_facecolor(color)
        ax.add_collection3d(poly3d)
        
        # 设置坐标轴范围
        max_range = max(w, h, d)
        mid_x, mid_y, mid_z = x + w/2, y + d/2, z + h/2
        ax.set_xlim(mid_x - max_range, mid_x + max_range)
        ax.set_ylim(mid_y - max_range, mid_y + max_range)
        ax.set_zlim(mid_z - max_range, mid_z + max_range)
        
    def _create_cylinder(self, ax, params):
        """创建圆柱体"""
        radius = params["radius"]
        height = params["height"]
        x, y, z = params["position"]
        color = params["color"]
        segments = params["segments"]
        
        # 创建圆柱体的顶部和底部圆
        theta = np.linspace(0, 2*np.pi, segments)
        x_circle = radius * np.cos(theta) + x
        y_circle = radius * np.sin(theta) + y
        
        # 底部圆
        z_bottom = np.ones_like(theta) * z
        ax.plot(x_circle, y_circle, z_bottom, color='black', alpha=0.6)
        
        # 顶部圆
        z_top = np.ones_like(theta) * (z + height)
        ax.plot(x_circle, y_circle, z_top, color='black', alpha=0.6)
        
        # 创建圆柱体侧面
        for i in range(segments):
            i_next = (i + 1) % segments
            x_points = [x_circle[i], x_circle[i], x_circle[i_next], x_circle[i_next]]
            y_points = [y_circle[i], y_circle[i], y_circle[i_next], y_circle[i_next]]
            z_points = [z_bottom[i], z_top[i], z_top[i_next], z_bottom[i_next]]
            vertices = [[x_points[j], y_points[j], z_points[j]] for j in range(4)]
            poly3d = Poly3DCollection([vertices], alpha=0.95, linewidths=0.5, edgecolors='black')
            poly3d.set_facecolor(color)
            ax.add_collection3d(poly3d)
            
        # 设置坐标轴范围
        max_range = max(radius*2, height)
        mid_x, mid_y, mid_z = x, y, z + height/2
        ax.set_xlim(mid_x - max_range, mid_x + max_range)
        ax.set_ylim(mid_y - max_range, mid_y + max_range)
        ax.set_zlim(mid_z - max_range/2, mid_z + max_range/2)
        
    def _create_pyramid(self, ax, params):
        """创建金字塔"""
        w = params["width"]
        h = params["height"]
        x, y, z = params["position"]
        color = params["color"]
        
        # 定义5个顶点（4个底部顶点和1个顶部顶点）
        vertices = [
            [x, y, z], [x+w, y, z], [x+w, y+w, z], [x, y+w, z],  # 底部顶点
            [x+w/2, y+w/2, z+h]  # 顶部顶点
        ]
        
        # 定义5个面（1个底面和4个侧面）
        faces = [
            [vertices[0], vertices[1], vertices[2], vertices[3]],  # 底面
            [vertices[0], vertices[1], vertices[4]],  # 侧面1
            [vertices[1], vertices[2], vertices[4]],  # 侧面2
            [vertices[2], vertices[3], vertices[4]],  # 侧面3
            [vertices[3], vertices[0], vertices[4]]   # 侧面4
        ]
        
        # 创建3D多边形集合
        poly3d = Poly3DCollection(faces, alpha=0.95, linewidths=1, edgecolors='black')
        poly3d.set_facecolor(color)
        ax.add_collection3d(poly3d)
        
        # 设置坐标轴范围
        max_range = max(w, h)
        mid_x, mid_y, mid_z = x + w/2, y + w/2, z + h/2
        ax.set_xlim(mid_x - max_range, mid_x + max_range)
        ax.set_ylim(mid_y - max_range, mid_y + max_range)
        ax.set_zlim(mid_z - max_range/2, mid_z + max_range)
        
    def _create_sphere(self, ax, params):
        """创建球体"""
        radius = params["radius"]
        x, y, z = params["position"]
        color = params["color"]
        segments = params["segments"]
        
        # 创建球体的经纬线
        u = np.linspace(0, 2 * np.pi, segments)
        v = np.linspace(0, np.pi, segments)
        
        # 计算球体表面点的坐标
        x_sphere = radius * np.outer(np.cos(u), np.sin(v)) + x
        y_sphere = radius * np.outer(np.sin(u), np.sin(v)) + y
        z_sphere = radius * np.outer(np.ones(np.size(u)), np.cos(v)) + z
        
        # 绘制球体
        ax.plot_surface(x_sphere, y_sphere, z_sphere, color=color, alpha=0.95, edgecolor='black', linewidth=0.5)
        
        # 设置坐标轴范围
        max_range = radius * 2
        mid_x, mid_y, mid_z = x, y, z
        ax.set_xlim(mid_x - max_range/2, mid_x + max_range/2)
        ax.set_ylim(mid_y - max_range/2, mid_y + max_range/2)
        ax.set_zlim(mid_z - max_range/2, mid_z + max_range/2)
        
    def _create_building(self, ax, params):
        """创建建筑物"""
        w, h, d = params["width"], params["height"], params["depth"]
        x, y, z = params["position"]
        color = params["color"]
        
        # 基础建筑是一个长方体
        self._create_cuboid(ax, params)
        
        # 添加屋顶（简单的三角形屋顶）
        roof_height = h * 0.2
        roof_vertices = [
            [x, y, z+h], [x+w, y, z+h], [x+w, y+d, z+h], [x, y+d, z+h],
            [x+w/2, y, z+h+roof_height], [x+w/2, y+d, z+h+roof_height]
        ]
        
        roof_faces = [
            [roof_vertices[0], roof_vertices[1], roof_vertices[4]],  # 前屋顶
            [roof_vertices[2], roof_vertices[3], roof_vertices[5]],  # 后屋顶
            [roof_vertices[1], roof_vertices[2], roof_vertices[5], roof_vertices[4]],  # 右屋顶
            [roof_vertices[3], roof_vertices[0], roof_vertices[4], roof_vertices[5]]   # 左屋顶
        ]
        
        roof_color = self._darken_color(color, 0.8)
        roof_poly = Poly3DCollection(roof_faces, alpha=0.95, linewidths=1, edgecolors='black')
        roof_poly.set_facecolor(roof_color)
        ax.add_collection3d(roof_poly)
        
        # 添加窗户
        window_width = w * 0.15
        window_height = h * 0.15
        window_depth = 0.01
        window_color = "#87CEEB"  # 天蓝色
        
        # 前面窗户
        for i in range(3):
            for j in range(3):
                if i == 1 and j == 1:  # 中间位置放门
                    continue
                window_x = x + w * 0.2 + i * w * 0.3
                window_y = y - window_depth
                window_z = z + h * 0.2 + j * h * 0.3
                
                window_vertices = [
                    [window_x, window_y, window_z], 
                    [window_x + window_width, window_y, window_z],
                    [window_x + window_width, window_y, window_z + window_height], 
                    [window_x, window_y, window_z + window_height]
                ]
                
                window_face = [window_vertices]
                window_poly = Poly3DCollection(window_face, alpha=0.8, linewidths=0.5, edgecolors='black')
                window_poly.set_facecolor(window_color)
                ax.add_collection3d(window_poly)
        
    def _create_tower(self, ax, params):
        """创建塔楼"""
        w, h, d = params["width"], params["height"], params["depth"]
        x, y, z = params["position"]
        color = params["color"]
        
        # 塔身（圆柱体）
        tower_params = params.copy()
        tower_params["radius"] = min(w, d) / 2
        tower_params["height"] = h * 0.8
        self._create_cylinder(ax, tower_params)
        
        # 塔顶（圆锥体）
        top_height = h * 0.2
        top_radius = tower_params["radius"]
        top_x, top_y = x, y
        top_z = z + tower_params["height"]
        segments = params["segments"]
        
        # 创建圆锥底部圆
        theta = np.linspace(0, 2*np.pi, segments)
        x_circle = top_radius * np.cos(theta) + top_x
        y_circle = top_radius * np.sin(theta) + top_y
        z_bottom = np.ones_like(theta) * top_z
        
        # 创建圆锥顶点
        top_point = [top_x, top_y, top_z + top_height]
        
        # 创建圆锥侧面
        for i in range(segments):
            i_next = (i + 1) % segments
            vertices = [
                [x_circle[i], y_circle[i], z_bottom[i]],
                [x_circle[i_next], y_circle[i_next], z_bottom[i_next]],
                top_point
            ]
            
            poly3d = Poly3DCollection([vertices], alpha=0.95, linewidths=0.5, edgecolors='black')
            top_color = self._darken_color(color, 0.7)
            poly3d.set_facecolor(top_color)
            ax.add_collection3d(poly3d)
            
    def _darken_color(self, hex_color, factor=0.7):
        """使颜色变暗"""
        # 移除#号
        hex_color = hex_color.lstrip('#')
        
        # 转换为RGB
        r = int(hex_color[0:2], 16)
        g = int(hex_color[2:4], 16)
        b = int(hex_color[4:6], 16)
        
        # 变暗
        r = int(r * factor)
        g = int(g * factor)
        b = int(b * factor)
        
        # 转回十六进制
        return f"#{r:02x}{g:02x}{b:02x}"
        
    def export_obj(self, text_description, output_filename=None):
        """导出OBJ格式的3D模型文件"""
        params = self.parse_text(text_description)
        
        if params["type"] not in self.shapes:
            raise ValueError(f"不支持的形状类型: {params['type']}")
            
        if not output_filename:
            output_filename = f"{params['type']}_{int(params['width'])}x{int(params['height'])}"
            
        # 根据形状类型生成顶点和面
        vertices = []
        faces = []
        
        if params["type"] in ["cube", "cuboid", "building"]:
            w, h, d = params["width"], params["height"], params["depth"]
            x, y, z = params["position"]
            
            # 定义8个顶点
            vertices = [
                [x, y, z], [x+w, y, z], [x+w, y+d, z], [x, y+d, z],
                [x, y, z+h], [x+w, y, z+h], [x+w, y+d, z+h], [x, y+d, z+h]
            ]
            
            # 定义6个面（每个面由4个顶点索引组成）
            # OBJ索引从1开始
            faces = [
                [1, 2, 3, 4],  # 底面
                [5, 6, 7, 8],  # 顶面
                [1, 2, 6, 5],  # 前面
                [2, 3, 7, 6],  # 右面
                [3, 4, 8, 7],  # 后面
                [4, 1, 5, 8]   # 左面
            ]
            
        elif params["type"] == "pyramid":
            w = params["width"]
            h = params["height"]
            x, y, z = params["position"]
            
            # 定义5个顶点
            vertices = [
                [x, y, z], [x+w, y, z], [x+w, y+w, z], [x, y+w, z],  # 底部顶点
                [x+w/2, y+w/2, z+h]  # 顶部顶点
            ]
            
            # 定义5个面
            faces = [
                [1, 2, 3, 4],  # 底面
                [1, 2, 5],     # 侧面1
                [2, 3, 5],     # 侧面2
                [3, 4, 5],     # 侧面3
                [4, 1, 5]      # 侧面4
            ]
            
        elif params["type"] in ["cylinder", "tower"]:
            radius = params["radius"]
            height = params["height"]
            x, y, z = params["position"]
            segments = params["segments"]
            
            # 创建底部和顶部圆的顶点
            for i in range(segments):
                angle = 2 * np.pi * i / segments
                # 底部圆顶点
                vertices.append([x + radius * np.cos(angle), y + radius * np.sin(angle), z])
                # 顶部圆顶点
                vertices.append([x + radius * np.cos(angle), y + radius * np.sin(angle), z + height])
            
            # 创建侧面
            for i in range(segments):
                i_next = (i + 1) % segments
                v1 = i * 2 + 1        # 当前底部顶点
                v2 = i_next * 2 + 1   # 下一个底部顶点
                v3 = i_next * 2 + 2   # 下一个顶部顶点
                v4 = i * 2 + 2        # 当前顶部顶点
                faces.append([v1, v2, v3, v4])
                
            # 创建底部和顶部圆面
            bottom_face = list(range(1, segments*2, 2))
            top_face = list(range(2, segments*2+1, 2))
            top_face.reverse()  # 反转顶面顶点顺序，使法向量朝外
            faces.append(bottom_face)
            faces.append(top_face)
            
        elif params["type"] == "sphere":
            radius = params["radius"]
            x, y, z = params["position"]
            segments = params["segments"]
            
            # 创建球体顶点
            for i in range(segments+1):
                phi = np.pi * i / segments
                for j in range(segments):
                    theta = 2 * np.pi * j / segments
                    vx = x + radius * np.sin(phi) * np.cos(theta)
                    vy = y + radius * np.sin(phi) * np.sin(theta)
                    vz = z + radius * np.cos(phi)
                    vertices.append([vx, vy, vz])
            
            # 创建球体面
            for i in range(segments):
                for j in range(segments):
                    v1 = i * segments + j + 1
                    v2 = i * segments + (j + 1) % segments + 1
                    v3 = (i + 1) * segments + (j + 1) % segments + 1
                    v4 = (i + 1) * segments + j + 1
                    
                    if i == 0:  # 顶部极点附近的三角形
                        faces.append([v1, v2, v4])
                    elif i == segments - 1:  # 底部极点附近的三角形
                        faces.append([v1, v2, v3])
                    else:  # 中间的四边形
                        faces.append([v1, v2, v3, v4])
        
        # 写入OBJ文件
        output_path = os.path.join(self.output_dir, f"{output_filename}.obj")
        with open(output_path, "w") as f:
            f.write(f"# 由TextTo3DGenerator生成的{params['type']}模型\n")
            f.write(f"# 参数: 宽={params['width']}, 高={params['height']}, 深={params['depth']}\n")
            
            # 写入顶点
            for v in vertices:
                f.write(f"v {v[0]} {v[1]} {v[2]}\n")
                
            # 写入面
            for face in faces:
                f.write("f " + " ".join([str(idx) for idx in face]) + "\n")
                
        return output_path


def main():
    """主函数"""
    generator = TextTo3DGenerator(output_dir="output/text3d")
    
    if len(sys.argv) > 1:
        if sys.argv[1] == "multi_cubes":
            # 生成多个立方体的示例
            print("生成多个立方体示例...")
            
            # 示例1：三个不同大小和颜色的立方体
            cubes_params1 = [
                {'size': [5, 5, 5], 'position': [0, 0, 0], 'color': '#FF0000'},  # 红色立方体在中心
                {'size': [3, 3, 3], 'position': [8, 0, 0], 'color': '#00FF00'},  # 绿色立方体在右侧
                {'size': [2, 2, 2], 'position': [0, 8, 0], 'color': '#0000FF'}   # 蓝色立方体在前方
            ]
            generator.generate_multi_cubes(cubes_params1, "multi_cubes_example1")
            
            # 示例2：堆叠的立方体
            cubes_params2 = [
                {'size': [10, 2, 10], 'position': [0, 0, 0], 'color': '#A52A2A'},  # 底部棕色立方体
                {'size': [8, 2, 8], 'position': [0, 0, 2], 'color': '#FFA500'},    # 中间橙色立方体
                {'size': [6, 2, 6], 'position': [0, 0, 4], 'color': '#FFFF00'},    # 顶部黄色立方体
                {'size': [2, 6, 2], 'position': [0, 0, 7], 'color': '#FF0000'}     # 顶部红色柱子
            ]
            generator.generate_multi_cubes(cubes_params2, "multi_cubes_example2")
            
            # 示例3：围绕中心的立方体阵列
            cubes_params3 = []
            colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF']
            for i in range(8):
                angle = i * np.pi / 4
                x = 8 * np.cos(angle)
                y = 8 * np.sin(angle)
                color = colors[i % len(colors)]
                cubes_params3.append({'size': [2, 2, 2], 'position': [x, y, 0], 'color': color})
            # 添加中心立方体
            cubes_params3.append({'size': [4, 4, 4], 'position': [0, 0, 0], 'color': '#FFFFFF'})
            generator.generate_multi_cubes(cubes_params3, "multi_cubes_example3")
            
            print("多立方体示例已生成完成！")
        else:
            # 从命令行参数获取文本描述
            text_description = " ".join(sys.argv[1:])
            output_path = generator.generate_model(text_description)
            print(f"已生成3D模型: {output_path}")
    else:
        # 示例
        examples = [
            "创建一个红色的立方体，宽度10，高度10，深度10",
            "创建一个蓝色的圆柱体，半径5，高度15",
            "创建一个绿色的金字塔，宽度12，高度20",
            "创建一个黄色的球体，半径8",
            "创建一个棕色的建筑，宽度20，高度30，深度15",
            "创建一个灰色的塔楼，宽度15，高度40，深度15"
        ]
        
        for i, example in enumerate(examples):
            output_path = generator.generate_model(example, f"example_{i+1}")
            print(f"示例{i+1}: {example}")
            print(f"已生成3D模型: {output_path}")
            
            # 导出OBJ文件
            obj_path = generator.export_obj(example, f"example_{i+1}")
            print(f"已导出OBJ文件: {obj_path}")
            print()
        
        print("\n要生成多个立方体示例，请运行: python textGen3D.py multi_cubes")


if __name__ == "__main__":
    main()